home *** CD-ROM | disk | FTP | other *** search
/ Skunkware 5 / Skunkware 5.iso / src / Games / net3d-0.08 / server.c < prev    next >
C/C++ Source or Header  |  1995-06-22  |  7KB  |  277 lines

  1. /* server.c
  2.  *
  3.  * Contains code needed to start and run the game server.
  4.  */
  5. #include "net3d.h"
  6. #include <netdb.h>
  7. #include <netinet/in.h>
  8.  
  9. static void displayhelp(char *);
  10.  
  11. int main(int argc, char **argv)
  12. {
  13. int mainsock;            /* socket used for accepting new players */
  14. int psocks[MAX_PLAYERS];    /* sockets connecting to players */
  15. fd_set fds;            /* file descriptors for select */
  16. int plcount=0;            /* number of players */
  17. char *pnames[MAX_PLAYERS];    /* names of players */
  18. struct object *ohead=NULL;    /* object list */
  19. struct vehicle *vhead=NULL;    /* vehicle list */
  20. struct map mp={NULL, NULL, 0, 0, 0.0, 0.0, {0,0,300}};
  21.                 /* game world terrain details */
  22. struct vehicle *vpos;        /* vehicle assigned to each player */
  23. struct vehicle *pvehicles[MAX_PLAYERS];
  24.                 /* vehicles owned by players */
  25. int finalcountdown=100;        /* frames between death of the last
  26.                  * player and the end of the game */
  27. char *filepaths[50];        /* actual paths to .v files given on
  28.                  * command line */
  29.  
  30. int i;                /* scratch variables */
  31. int j;
  32.  
  33. if (argc == 1) {
  34.     printf("usage : Server mode : %s <vehicle files>\n",argv[0]);
  35.     printf("        Help        : %s -help\n",argv[0]);
  36.     exit(0);
  37.     }
  38. if (!strcmp(argv[1],"-help")) {
  39.     displayhelp(argv[0]);
  40.     exit(0);
  41.     }
  42.  
  43. /* We want children reaped automatically by default. */
  44. signal(SIGCHLD, SIG_IGN);
  45.  
  46. initcaches();
  47. readextravehicles();        /* read extra vehicles from internal array */
  48.  
  49. /* For each vehicle file on the command line, pass it through cpp
  50.  * before reading into the object and vehicle lists. 
  51.  */
  52. for(i=1; i<argc; i++) {
  53.     int pifd;        /* file descriptor for pipe */
  54.     struct stat dummy;
  55.     char currentdir[100];    /* path to .v file in current dir */
  56.     char net3ddir[100];    /* path to .v file in NET3D_DIR */
  57.  
  58.     /* Look for the file in the current directory and in NET3D_DIR,
  59.      * then pipe it through cpp.
  60.      */
  61.     sprintf(currentdir,"%s",argv[i]);
  62.     sprintf(net3ddir,"%s/%s",NET3D_DIR,argv[i]);
  63.     if (stat(currentdir,&dummy) != -1) {
  64.         pifd=pipethrough(CPPPATH,currentdir);
  65.         readfile(&ohead,&vhead,pifd,&mp);
  66.         printf("done reading %s\n",currentdir);
  67.         close(pifd);
  68.         filepaths[i] = strdupe(currentdir);
  69.         }
  70.     else if (stat(net3ddir,&dummy) != -1) {
  71.         pifd=pipethrough(CPPPATH,net3ddir);
  72.         readfile(&ohead,&vhead,pifd,&mp);
  73.         printf("done reading %s\n",net3ddir);
  74.         close(pifd);
  75.         filepaths[i] = strdupe(net3ddir);
  76.         }
  77.     else {
  78.         printf("file %s not found\n",argv[i]);
  79.         exit(0);
  80.         }
  81.     }
  82.  
  83. /* check if a sensible world was read in */
  84. if (vhead==NULL) {
  85.     printf("No vehicles available for use\n");
  86.     exit(1);
  87.     }
  88. else {
  89.     makemap(&ohead,&mp);
  90.     worldinfo(vhead,ohead);
  91.     printf("Waiting for players... hit return to start game\n");
  92.     }
  93.  
  94. /* open initial socket for connections from clients */
  95. mainsock=OpenDest();
  96.  
  97. do {
  98.     /* wait for either a key-press or a new connection */
  99.     FD_ZERO(&fds);
  100.     FD_SET(0,&fds);
  101.     FD_SET(mainsock,&fds);
  102. #ifdef __hpux
  103.     select(mainsock+1,(int *)&fds,NULL,NULL,NULL);
  104. #else
  105.     select(mainsock+1,&fds,NULL,NULL,NULL);
  106. #endif
  107.  
  108.     if (FD_ISSET(mainsock,&fds)) {
  109.         char *hname;
  110.  
  111.         /* A new connection has arrived.
  112.          */
  113.         struct sockaddr_in newaddr;
  114.         struct hostent *newhost;
  115.         int newaddrsize;
  116.  
  117.         /* accept incoming connection, and find the address
  118.          * of the sender. */
  119.         newaddrsize = sizeof(newaddr);
  120.         psocks[plcount]=accept(mainsock,(struct sockaddr *)
  121.                        &newaddr,&newaddrsize);
  122.         newhost = gethostbyaddr((char *)&newaddr.sin_addr.s_addr,
  123.                     4,AF_INET);
  124.         hname = newhost ? newhost->h_name : "unknown";
  125.  
  126.         /* tell player the version number */
  127.         nprintf(psocks[plcount],"%s\n",NET3D_VERSION);
  128.  
  129.         /* get name from player, or version error */
  130.         pnames[plcount]=strdupe(ngets(psocks[plcount]));
  131.         if (!strcmp(pnames[plcount],VERSION_ERROR)) {
  132.             printf("player on machine %s has wrong version..."
  133.                 "rejected\n",hname);
  134.             close(psocks[plcount]);
  135.             }
  136.         else {
  137.             printf("received connection from %s on %s\n",
  138.                 pnames[plcount],hname);
  139.             plcount++;
  140.             }
  141.         }
  142.     } while(!FD_ISSET(0,&fds));
  143.  
  144. if (plcount)
  145.     printf("starting game with %d players\n",plcount);
  146. else {
  147.     printf("no players :(\n");
  148.     exit(0);
  149.     }
  150.  
  151. /* list all players */
  152. for(i=0; i<plcount; i++)
  153.     printf("Player %d is \"%s\"\n",i,pnames[i]);
  154.  
  155. /* once again, run all the vehicle files through cpp, but this time
  156.  * send them through the sockets to each client
  157.  */
  158. for(i=1; i<argc; i++) {
  159.     char syscom[100];    /* buffer used for 'popen' call */
  160.     FILE *pifp;        /* file pointer for 'popen' call */
  161.  
  162.     sprintf(syscom,"%s %s",CPPPATH,filepaths[i]);
  163.     pifp=popen(syscom,"r");
  164.     while(!feof(pifp)) {
  165.         char buf[100];    /* a line from the pre-processor */
  166.         int j;
  167.  
  168.         /* read a line, and send it to all clients */
  169.         fgets(buf,100,pifp);
  170.         for(j=0; j<plcount; j++)
  171.             nprintf(psocks[j],"%s",buf);
  172.         }
  173.     pclose(pifp);
  174.     for(j=0; j<plcount; j++)
  175.         nprintf(psocks[j],"\n");
  176.     printf("done transmitting %s\n",filepaths[i]);
  177.     }
  178. /* send the 'end' token to all clients, to indicate the end of
  179.  * the vehicle files
  180.  */
  181. for(i=0; i<plcount; i++)
  182.     nprintf(psocks[i],"\nend\n");
  183.  
  184. /* tell each client their player number */
  185. vpos=vhead;
  186. for(i=0; i<plcount; i++) {
  187.     if (vpos) {
  188.         printf("%s has vehicle %s\n",pnames[i],vpos->code);
  189.         nprintf(psocks[i],"%d\n",i);
  190.         vpos=vpos->next;
  191.         }
  192.     else {
  193.         printf("player %d has no vehicle!!\n",i);
  194.         break;
  195.         }
  196.     }
  197. /* send 'no vehicle' signal to all clients who don't have a vehicle */
  198. j=i;
  199. for(; i<plcount; i++) {
  200.     nprintf(psocks[i],"-1\n",i);
  201.     shutdown(psocks[i],2);
  202.     close(psocks[i]);
  203.     }
  204. /* truncate player list to the number who got vehicles */
  205. plcount=j;
  206. stillalive=plcount;
  207.  
  208. /* tell each client the number of players in the game, and the names
  209.  * of the players.
  210.  */
  211. for(i=0; i<plcount; i++) {
  212.     int j;
  213.     nprintf(psocks[i],"%d\n",plcount);
  214.     for(j=0; j<plcount; j++)
  215.         nprintf(psocks[i],"%s\n",pnames[j]);
  216.     }
  217.  
  218. /* store the vehicles owned by each player */
  219. vpos=vhead;
  220. for(i=0; i<plcount; i++) {
  221.     pvehicles[i]=vpos;
  222.     vpos=vpos->next;
  223.     }
  224.     
  225. /* send to each client a message consisting only of the game time,
  226.  * to start each client up.
  227.  */
  228. for(i=0; i<plcount; i++)
  229.     nprintf(psocks[i],"%lf\n",gametime());
  230.  
  231. /* The main server loop.
  232.  *
  233.  * In here, we wait for all the clients to reply with their commands,
  234.  * and once done, send gametime() and those commands to all clients.
  235.  */
  236. while(stillalive || finalcountdown) {
  237.     processnet(psocks,plcount,mainsock);
  238.     if (!stillalive)
  239.         finalcountdown--;
  240.     }
  241.  
  242. /* no-one is left. Send quit messages to all clients */
  243. printf("All players destroyed. GAME OVER\n");
  244. for(i=0; i<plcount; i++)
  245.     nprintf(psocks[i],"%lf q 0 0.0\n",gametime());
  246.  
  247. /* close all connections to players and the main socket
  248.  */
  249. for(i=0; i<plcount;i++) {
  250.     shutdown(psocks[i],2);
  251.     close(psocks[i]);
  252.     }
  253. shutdown(mainsock,2);
  254. close(mainsock);
  255. return(0);
  256. }
  257.  
  258. static void displayhelp(char *cn)
  259. {
  260. printf(
  261. "net3d server help\n"
  262. "-----------------\n"
  263. "Server mode : To start the net3d server, type :\n"
  264. "              %s <vehicle file> <vehicle file> ...\n"
  265. "              Vehicle files have the extension .v, and at least one must\n"
  266. "              be given."
  267. "\n"
  268. "              Once the server has started, it will wait for net3d clients\n"
  269. "              to connect, and display connections as they are received.\n"
  270. "              When enough connections have arrived, and you want to start\n"
  271. "              the game, hit return. Each player will be given a vehicle, and\n"
  272. "              the game will start\n"
  273. ,cn);
  274. }
  275.  
  276.  
  277.